\section{QThread}
使用类QThread开始一个线程，实现它的字类覆盖调QThread.run()函数。
\pythonfile{code/QThread/ex1.py}
\subsection{常用方法}
\begin{itemize}
	\item start()：启动线程
	\item wait()：阻止线程
	\item sleep(s)：强制当前进程休眠s秒
\end{itemize}
\subsection{QThread常用的信号}
\begin{itemize}
	\item started：在开始执行run()函数之前从相关的线程发射此信号
\item 在程序完成业务逻辑时，从相关线程发射此信号
\end{itemize}
\begin{remark}
	当在窗口中显示的数据比较简单时，可以把读取数据的业务逻辑放在窗口的初始化代码中；但如果读取数据的时间比较长，比如网络请求数据的时间比较长，则可以把这部分逻辑放在QThread线程中，实现界面的数据显示和数据读取的分离.
\end{remark}
\pythonfile{code/QThread/ex2.py}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.5\textwidth]{Qthread1.png}
	\caption{QThread线程}
\end{figure}
线程构造过程如下：
\begin{figure}[H]
	\centering
	\includegraphics[width=0.5\textwidth]{QThread}
	\caption{线程构造和信号发送}
\end{figure}
上一个例子中，虽然解决了界面的数据显示和数据读取的分离，但是如果数据的读取非常消耗时间，则会造成界面卡死，下面是一个需要耗费很长时间读取数据的例子
\pythonfile{code/QThread/ex3.py}
\begin{figure}[H]
	\centering
	\includegraphics[width=0.5\textwidth]{qthread_ex3}
	\caption{界面卡死}
\end{figure}
正常情况下，在点击按钮之后，LCD上的数字会随着时间发生变化，但是在实际运行过程中会发现点击按钮之后，程序界面直接停止响应，直到循环结束才开始重新更新，于是计时器始终显示为0。

\begin{remark}
	在上面这个程序中没有引入新的线程，PyQt中所有的窗口都在UI主线程中（就是执行了QApplication.exec()的线程），在这个线程中执行耗时的操作会阻塞UI线程，从而让窗口停止响应。
\end{remark}
分离主线程和工作线程
\pythonfile{code/QThread/ex4.py}

\begin{remark}
	按下按钮后，计时器开始计数，并启动一个新的线程，在这个线程里，执行一个循环并在循环结束时发送完成信号，在完成信号发出后，执行与之相关联的槽函数，关闭定时器。
\end{remark}

\textit{事件处理}

对于执行很耗时的程序来说，由于PyQt需要等待程序执行完毕才能进行下一步，这个过程表现在界面上就是卡顿；而如果在执行这个耗时程序时不断地运行QApplication.processEvents()，那么就可以实现一边执行耗时程序，一边刷新页面的功能，会给人一种相对更流畅的感觉，QApplication.processEvents()的使用方法是，在主函数执行耗时操作的地方，加入QApplication.processEvents()，processEvents()函数的使用方法简单来说就是刷新页面。
\pythonfile{code/QThread/ex4.py}
如果不添加QApplication.processEvents()，会在卡顿之后显示输出全部结果，添加之后，也不能保证每个都是逐行显示，只是比不加相对流畅一点，效果是不如多线程的。
